﻿/*
 * Разработчик: Коледа Андрей
 * Дата: 25.01.2011
 * Время: 17:06
 * Email: koleda.andrey@gmail.com
 */
using System;
using System.Collections.Generic;
using System.Linq;
using FastTravel.DataAccess.Base;
using FastTravel.DataAccess.Interface;
using FastTravel.DB;
using FastTravel.DB.Enums;
using FastTravel.Utilites;
using StructureMap;

namespace FastTravel.BusinessLogic
{
	/// <summary>
	/// Управление клиентами
	/// </summary>
	public static class CustomerManager
	{
		/// <summary>
		/// Хранилище клиентов
		/// </summary>
		private static IRepository<Customer> CustomerRepository
		{
			get{return ObjectFactory.GetInstance<IRepository<Customer>>();}
		}

		/// <summary>
		/// Хранилище паспортов
		/// </summary>
		private static IRepository<Passport> PassportRepository
		{
			get { return ObjectFactory.GetInstance<IRepository<Passport>>(); }
		}

		/// <summary>
		/// Хранилище сканов
		/// </summary>
		private static IRepository<Scan> ScanRepository
		{
			get { return ObjectFactory.GetInstance<IRepository<Scan>>(); }
		}

		/// <summary>
		/// Хранилище заказов
		/// </summary>
		private static IRepository<Order> OrderRepository
		{
			get { return ObjectFactory.GetInstance<IRepository<Order>>(); }
		}

		/// <summary>
		/// Создать клиента
		/// </summary>
		/// <param name="firstName">Имя</param>
		/// <param name="lastName">Фамилия</param>
		/// <param name="middleName">Отчество</param>
		/// <param name="homePhone">Домашний телефон</param>
		/// <param name="workPhone">Рабочий телефон</param>
		/// <param name="mobilePhone">Мобильный телефон</param>
		/// <param name="profession">Профессия</param>
		/// <param name="jobPlasement">Место работы</param>
		/// <param name="marritalStatus">Семейное положение</param>
		/// <param name="address1">Адрес 1</param>
		/// <param name="address2">Адрес 2</param>
		/// <param name="birthDate">Дата рождения</param>
		/// <param name="email">Email</param>
		/// <returns>Клиент</returns>
		public static Customer Add (string firstName, string lastName, string middleName, Int64 homePhone, 
			Int64 workPhone, Int64 mobilePhone, string profession, string jobPlasement, MarritalStatus marritalStatus, 
			string address1, string address2, DateTime birthDate, string email)
		{
			Customer customer = new Customer
									{
										IsArchive = false,
										AddedDate = DateTime.Now,
										JobPlacement = jobPlasement,
										Profession = profession,
										FirstName = TextFormatHelper.FormatName(firstName),
										LastName = TextFormatHelper.FormatName(lastName),
										MiddleName = TextFormatHelper.FormatName(middleName),
										MarritalStatus = marritalStatus,
										PhoneHome = homePhone,
										PhoneWork = workPhone,
										PhoneMobile = mobilePhone,
										AddressLine1 = address1,
										AddressLine2 = address2,
										BirthDate = birthDate,
										Email = email,
										ModifyDate = DateTime.Now
									};

			CustomerRepository.Add(customer);
			return customer;
		}

		/// <summary>
		/// Обновление клиента
		/// </summary>
		/// <param name="customerId">Идентификатор клиента</param>
		/// <param name="firstName">Имя</param>
		/// <param name="lastName">Фамилия</param>
		/// <param name="middleName">Отчество</param>
		/// <param name="homePhone">Домашний телефон</param>
		/// <param name="workPhone">Рабочий телефон</param>
		/// <param name="mobilePhone">Мобильный телефон</param>
		/// <param name="profession">Профессия</param>
		/// <param name="jobPlasement">Место работы</param>
		/// <param name="marritalStatus">Семейный статус</param>
		/// <param name="address1">Адрес 1</param>
		/// <param name="address2">Адрес 2</param>
		/// <param name="birthDate">Дата рождения</param>
		/// <param name="email">Email</param>
		public static void Update(int customerId, string firstName, string lastName, string middleName, Int64 homePhone, 
			Int64 workPhone, Int64 mobilePhone, string profession, string jobPlasement, MarritalStatus marritalStatus, 
			string address1, string address2, DateTime birthDate, string email)
		{
			Customer customer = CustomerRepository.Single(x => x.ID == customerId);
			if (customer != null)
			{
				customer.FirstName = TextFormatHelper.FormatName(firstName);
				customer.LastName = TextFormatHelper.FormatName(lastName);
				customer.MiddleName = TextFormatHelper.FormatName(middleName);
				customer.PhoneHome = homePhone;
				customer.PhoneWork = workPhone;
				customer.PhoneMobile = mobilePhone;
				customer.Profession = profession;
				customer.JobPlacement = jobPlasement;
				customer.MarritalStatus = marritalStatus;
				customer.AddressLine1 = address1;
				customer.AddressLine2 = address2;
				customer.BirthDate = birthDate;
				customer.Email = email;
				customer.ModifyDate = DateTime.Now;

				CustomerRepository.SaveChanges();
			}
		}

		/// <summary>
		/// Добавить паспорт клиенту
		/// </summary>
		/// <param name="customerId">ID клиента</param>
		/// <param name="authority">Кем выдан</param>
		/// <param name="expirityDate">Дата окнчания</param>
		/// <param name="issueDate">Дата выдачи</param>
		/// <param name="number">Номер паспорта</param>
		/// <returns>Паспорт</returns>
		public static Passport AddPassport (int customerId, string authority, DateTime expirityDate, DateTime issueDate, string number)
		{			
			Passport passport = new Passport
			                    	{
			                    		ExpiryDate = expirityDate,
			                    		IssueDate = issueDate,
			                    		Number = number,
			                    		Authority = authority,
			                    		Customer = CustomerRepository.Single(x => x.ID == customerId)
			                    	};

			PassportRepository.Add(passport);
			return passport;
		}

		/// <summary>
		/// Обновление паспорта
		/// </summary>
		/// <param name="customerId">ID клиента</param>
		/// <param name="authority">Кем выдан</param>
		/// <param name="expirityDate">Дата до</param>
		/// <param name="issueDate">Дата с</param>
		/// <param name="number">Номер паспорта</param>
		public static void UpdatePassport(int customerId, string authority, DateTime expirityDate, DateTime issueDate, string number)
		{
			Customer customer = CustomerRepository.Single(x => x.ID == customerId);
			if (customer.Passport != null)
			{
				customer.Passport.ExpiryDate = expirityDate;
				customer.Passport.IssueDate = issueDate;
				customer.Passport.Number = number;
				customer.Passport.Authority = authority;
				CustomerRepository.SaveChanges();
			}
		}

		/// <summary>
		/// Добавить скан-копию клиенту
		/// </summary>
		/// <param name="customerId">ID клиента</param>
		/// <param name="name">Имя файла</param>
		/// <param name="description">Описание</param>
		/// <returns>Скан-копия</returns>
		public static Scan AddScan (int customerId, string name, string description)
		{
			Customer customer = CustomerRepository.Single(x => x.ID == customerId);
			if (customer != null)
			{
				Scan scan = new Scan { AddedDate = DateTime.Now, Description = description, Name = name };
				customer.Scan.Add(scan);
				ScanRepository.Add(scan);
				return scan;
			}
			return null;
		}

		/// <summary>
		/// Получить клиента
		/// </summary>
		/// <param name="id">ID</param>
		/// <returns>Клиент</returns>
		public static Customer Get(int id)
		{
			return CustomerRepository.Single(x => x.ID == id);
		}

		/// <summary>
		/// Получить паспорт клиента
		/// </summary>
		/// <param name="customerId">ID клиента</param>
		/// <returns>Паспорт</returns>
		public static Passport GetPassport(int customerId)
		{
			return PassportRepository.Single(x => x.Customer.ID == customerId);
		}

		/// <summary>
		/// Получить скан-копии
		/// </summary>
		/// <param name="customerId"></param>
		/// <returns></returns>
		public static IEnumerable<Scan> GetScan(int customerId)
		{
			return ScanRepository.GetQuery().Where(x => x.Customer.ID == customerId);
		}

		/// <summary>
		/// Получить всех клиентов
		/// </summary>
		/// <returns>Список клиентов</returns>
		public static IEnumerable<Customer> GetAll()
		{
			return CustomerRepository.GetAll();
		}

		/// <summary>
		/// Получить всех клиентов
		/// </summary>
		/// <param name="showDeleted">Учитывать удаленных</param>
		/// <returns>Список клиентов</returns>
		public static IEnumerable<Customer> GetAll(bool showDeleted)
		{
			return showDeleted
					   ? CustomerRepository.GetAll()
					   : CustomerRepository.GetQuery().Where(x => x.IsArchive == false);
		}

		/// <summary>
		///  Получить всех клиентов
		/// </summary>
		/// <param name="start">Начальная страница</param>
		/// <param name="limit">Размер страницы</param>
		/// <param name="sort">Сортировка по полю</param>
		/// <param name="dir">Направление сортировки</param>
		/// <param name="count">Общее число клиентов</param>
		/// <returns>Список клиентов</returns>
		public static List<Customer> GetPage(int start, int limit, string sort, string dir, out int count)
		{
			return CustomerRepository.GetPage(start, limit, sort, dir, out count);
		}

		/// <summary>
		///  Получить страницу клиентов
		/// </summary>
		/// <param name="start">Начальная страница</param>
		/// <param name="limit">Размер страницы</param>
		/// <param name="sort">Сортировка по полю</param>
		/// <param name="dir">Направление сортировки</param>
		/// <param name="showDeleted">Показвать удаленных</param>
		/// <param name="count">Общее число клиентов</param>
		/// <returns>Список клиентов</returns>
		public static List<Customer> GetPage(int start, int limit, string sort, string dir, bool showDeleted, out int count)
		{
			if (showDeleted)
			{
				return CustomerRepository.GetPage(start, limit, sort, dir, out count);
			}

			var result = CustomerRepository.GetQuery().Where(x => x.IsArchive == false).Select(e => e);
			if (!string.IsNullOrEmpty(sort))
			{
				result = dir == "ASC" 
				         	? CustomerRepository.SortByQuery<Customer>(result, sort, true) 
				         	: CustomerRepository.SortByQuery<Customer>(result, sort, false);
			}

			if (start >= 0 && limit > 0)
			{
				result = result.Skip(start).Take(limit);
			}
			count = CustomerRepository.GetQuery().Where(x => x.IsArchive == false).Count();

			return result.ToList();
		}

		/// <summary>
		/// Получить страницу клиентов
		/// </summary>
		/// <param name="start">Начальная страница</param>
		/// <param name="limit">Размер страницы</param>
		/// <param name="sort">Сортировка по полю</param>
		/// <param name="dir">Направление сортировки</param>
		/// <param name="showDeleted">Показывать удаленных</param>
		/// <param name="filterByFirstName">Фильтр по имени</param>
		/// <param name="filterByLastName">Фильтр по фамилии</param>
		/// <param name="filterByMiddleName">Фильтр по отчеству</param>
		/// <param name="count">Общее число клиентов</param>
		/// <returns>Список клиентов</returns>
		public static List<Customer> GetPage(int start, int limit, string sort, string dir, bool showDeleted, 
			string filterByFirstName, string filterByLastName, string filterByMiddleName, out int count)
		{
			var query = CustomerRepository.GetQuery().Select(e => e);
			
			if (!showDeleted)
			{
				query = query.Where(x => x.IsArchive == false);
			}

			if (!string.IsNullOrEmpty(filterByFirstName))
			{
				query = query.Where(x => x.FirstName.ToLower().StartsWith(filterByFirstName.ToLower()));
			}

			if (!string.IsNullOrEmpty(filterByLastName))
			{
				query = query.Where(x => x.LastName.ToLower().StartsWith(filterByLastName.ToLower()));
			}

			if (!string.IsNullOrEmpty(filterByMiddleName))
			{
				query = query.Where(x => x.MiddleName.ToLower().StartsWith(filterByMiddleName.ToLower()));
			}

			count = query.Count();

			if (!string.IsNullOrEmpty(sort))
			{
				query = dir == "ASC"
							? CustomerRepository.SortByQuery<Customer>(query, sort, true)
							: CustomerRepository.SortByQuery<Customer>(query, sort, false);
			}

			if (start >= 0 && limit > 0)
			{
				query = query.Skip(start).Take(limit);
			}

			return query.ToList();
		}


		/// <summary>
		/// Получить количество клиентов
		/// </summary>
		/// <returns>Количество</returns>
		public static int Count()
		{
			return CustomerRepository.GetQuery().Count();
		}

		/// <summary>
		/// Получить количество клиентов
		/// </summary>
		/// <param name="showDeleted">Учитывать удаленных клиентов</param>
		/// <returns>Количество</returns>
		public static int Count(bool showDeleted)
		{
			return showDeleted
					   ? CustomerRepository.GetQuery().Count()
					   : CustomerRepository.GetQuery().Where(x => x.IsArchive == false).Count();
		}

		/// <summary>
		/// Удалить клиента
		/// </summary>
		/// <param name="customerId">ID клиента</param>
		public static void Delete(int customerId)
		{
			Customer customer = CustomerRepository.Single(x => x.ID == customerId);

			var customerOrdersCount = OrderRepository.GetQuery().Where(c => c.OrderSet.Any(x => x.Customer.ID == customer.ID)).Count();

			if (customerOrdersCount > 0)
			{
				customer.IsArchive = true;
				CustomerRepository.SaveChanges();
			}
			else
			{
				// удаляем паспорт
				PassportRepository.Delete(customer.Passport);

				// удаляем скан-копии
				IEnumerable<Scan> scans = ScanRepository.GetQuery().Where(x => x.Customer.ID == customerId);
				foreach (var scan in scans)
				{
					ScanRepository.Delete(scan);
				}

				// удаляем клиента
				CustomerRepository.Delete(customer);
			}
		}

	}
}
